package com.zt.questionnaire.common.interceptor;

import com.zt.questionnaire.common.HService;
import com.zt.questionnaire.common.config.redis.CacheOperator;
import com.zt.questionnaire.common.utils.RegExpUtils;
import com.zt.questionnaire.common.utils.jwt.TokenUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;

/**
 * 所有消息的拦截器
 *
 * @author sy
 */
public class AllInterceptor extends HandlerInterceptorAdapter {

    Logger log = LoggerFactory.getLogger(AllInterceptor.class);

    @Autowired
    private CacheOperator redis;

    // 公司域名，拿到的是ip，不是域名，所以不可以
//	String url_company = "http://1o746k7976.51mypc.cn";
    // 公司ip是动态的，所以测试的时候是需要修改的
    private List<String> urlCompanyList = Arrays.asList("117.184.25.86", "114.86.228.218");

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
        throws Exception {
        String remoteAddr = request.getRemoteAddr();
        if (!RegExpUtils.isLanIp(remoteAddr) && !urlCompanyList.contains(remoteAddr)) {
            // 只能内外和公司ip能访问服务，用户所有访问消息都是通过网关转发的，安全验证也是在网关做的，网关和所有微服务都在同一个内网中
            log.error("url异常={}", remoteAddr);
            return false;
        }

        String url = request.getRequestURI();
        String method = request.getMethod().toUpperCase();

        log.info("=============================");
        StringBuilder param = new StringBuilder();
        Enumeration<String> paramNameEnum = request.getParameterNames();
        while (paramNameEnum.hasMoreElements()) {
            String paramName = paramNameEnum.nextElement();
            String paramValue = request.getParameter(paramName);
            param.append(paramName).append(" = ").append(paramValue).append(",");
        }
        log.info("请求URL: " + url);
        log.info("请求方式: " + method);
        log.info("请求参数: " + param);

        // 跨域
        response.setContentType("text/html;charset=utf-8");
//		response.addHeader("Access-Control-Allow-Headers","Origin, X-Requested-With, Content-Type, Accept, If-Modified-Since, ajax-cookie, token,source,tag,tam,sign");
////		response.addHeader("Access-Control-Allow-Headers","*");
//		response.addHeader("Access-Control-Allow-Credentials", "true");
//		response.addHeader("Access-Control-Allow-Methods", "GET,POST,OPTIONS");
//		response.addHeader("Access-Control-Allow-Origin", "*");
//		response.addHeader("Access-Control-Expose-Headers", "*");

        if (method.equals("OPTIONS")) {
            return false;
        }

        // 先默认过来的是患者，拿患者的账号id，当不上患者的时候是拿不到的，后面会进入管理员的拦截器的（目的是，统一获取患者的账号和封号验证，因为患者有的地方不需要token验证但是当登录的时候又需要账号id，每个需要的方法都要单独做获取账号的操作）
        String token = request.getHeader(HService.attr_req_token);
        String source = request.getHeader(HService.attr_req_source);
        String platform = request.getHeader(HService.attr_req_platform);
        String ver = request.getHeader(HService.attr_req_ver);
        log.info("token={},source={},platform={},ver={}", token, source, platform, ver);

        request.setAttribute(HService.attr_req_source, source);
        if (token == null || token.equals("") || token.toLowerCase().equals("null")) {
            // 协议没带token就不获取账号信息，如果必须要登录，后面的拦截器会拦截到的
            return true;
        }

        Map<String, Object> map = TokenUtils.validHS256(token, redis);
        if (map != null) {
            // 返回null表示token错误，还有一种情况，本身不需要验证的地方客户端也带了token，所以验证到token错误的时候不立即返回
            log.info("发起请求的用户信息={}", map);
            Set<String> keyNameList = map.keySet();
            for (String keyName : keyNameList) {
                request.setAttribute(keyName, map.get(keyName));
            }
//			request.setAttribute(HService.ATTR_admin, map.get(HService.ATTR_admin));
//			request.setAttribute(HService.ATTR_ID, map.get(HService.ATTR_ID));
//			request.setAttribute(HService.ATTR_name, map.get(HService.ATTR_name));
//			request.setAttribute(HService.ATTR_PHONE, map.get(HService.ATTR_PHONE));
//			request.setAttribute(HService.ATTR_type, map.get(HService.ATTR_type));
//			request.setAttribute(HService.ATTR_relation_id, map.get(HService.ATTR_relation_id));
            // 每个消息接收到后不再验证账号是否被封，每次只在登录的时候验证账号是否被封，因为账号被封的时候会删除token缓存，用户会强制重新登录，登录的时候就会发现账号被封
        }
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
                           ModelAndView modelAndView) throws Exception {
        /*
         * System.out.println(
         * ">>>MyInterceptor1>>>>>>>请求处理之后进行调用，但是在视图被渲染之前（Controller方法调用之后）");
         * super.postHandle(request, response, handler, modelAndView);
         */
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
        throws Exception {
        /*
         * System.out.
         * println(">>>MyInterceptor1>>>>>>>在整个请求结束之后被调用，也就是在DispatcherServlet 渲染了对应的视图之后执行（主要是用于进行资源清理工作）"
         * ); super.afterCompletion(request, response, handler, ex);
         */
    }

}
